<body></body>
<script>
  let activeEffect = null
  const bucket = new WeakMap()
  const data = {ok: true, text: 'hello vue'}
  const obj = new Proxy(data, {
    get: (target, key) => (activeEffect && track(target, key), target[key]),
    set: (target, key, newVal) => ((target[key] = newVal), trigger(target, key))
  })
  function track(target, key) {
    const depMap = bucket.get(target) || bucket.set(target, new Map()).get(target)
    const deps = depMap.get(key) || depMap.set(key, new Set()).get(key)
    deps.add(activeEffect)
    console.log(deps)

    activeEffect.deps.push(deps)
  }
  const trigger = (target, key) => new Set(bucket.get(target)?.get(key)).forEach(fn => fn())
  function effect(fn) {
    const effectFn = () => (cleanup(effectFn), (activeEffect = effectFn), fn())
    effectFn.deps = []
    effectFn()
  }
  const cleanup = effectFn => (effectFn.deps.forEach(dep => dep.delete(effectFn)), (effectFn.deps.length = 0))
  effect(() => ((document.body.innerText = obj.ok ? obj.text : 'not'), console.log('更新页面')))
  setTimeout(() => (obj.ok = false), 500)
  setTimeout(() => (obj.text = 1), 1000)
  setTimeout(() => (obj.text = 2), 2000)
  setTimeout(() => (obj.ok = true), 3500) //hello vue\not\2\3
  setTimeout(() => (obj.text = 3), 4000)
</script>
